package model;

public class Configuration {

	private State state;
	private final String input;
	private int position;
	private Output output;

	public int getPosition() {
		return position;
	}

	public String getInput() {
		return input;
	}

	public State getState() {
		return state;
	}

	public void setState(final State state) {
		this.state = state;
	}
	public Output getOutput() {
		return output;
	}

	public void setOutput(final Output output) {
		this.output = output;
	}	
	
	/**
	 * Factroy method of {@link Configuration}.
	 * Provides an {@link Error} if the position is greater than the length of the provided input string.
	 * @param state is the current {@link State} of this {@link Configuration}.
	 * @param input is the input of this {@link Configuration}.
	 * @param position	is a position within the provided input string that seperates the already
	 * 					processed input from the input that is not yet processed.
	 * @param output is the {@link Output} of this current {@link Configuration}.
	 * @return a new {@link Configuration}
	 */
	public static Configuration create(final State state, final String input, final int position, final Output output){
		if(position > input.length()) 
			throw new Error(position + " > " + input.length());
		return new Configuration(state, input, position,output);
	}
	
	/**
	 * Constructor of {@link Configuration}.
	 * @param state is the current {@link State} of this {@link Configuration}.
	 * @param input is the input of this {@link Configuration}.
	 * @param position	is a position within the provided input string that seperates the already
	 * 					processed input from the input that is not yet processed.
	 * @param output is the {@link Output} of this current {@link Configuration}.
	 */
	private Configuration(final State state, final String input, final int position,final Output output) {
		this.setState(state);
		this.input = input;
		this.position = position;
		this.setOutput(output);
	}

	/**
	 * Provides true if a char in the input string has not been processed.
	 * @return true if a chat in the input string has not been processed. Else false.
	 */
	public boolean hasInput() {
		return this.position < input.length();
	}
	
	/**
	 * Provides the next input char and increases the position by one.
	 * @return the next input char
	 */
	public char getNextInput(){
		if(this.hasInput()){
			final char result = this.input.charAt(this.position);
			this.position = this.position + 1;
			return result;
		} else {
			throw new Error("No input char left.");
		}
		
	}
}
